/**
 * Created by ${PRODUCT_NAME}.
 * User: skylerparr
 * Date: 12/23/10
 * Time: 6:43 AM
 * To change this template use File | Settings | File Templates.
 */
package com.thoughtorigin.meta {
import com.thoughtorigin.meta.mock.SampleDisplayObject;
import com.thoughtorigin.reflect.FunctionMetaDataItem;
import com.thoughtorigin.reflect.MetaArg;
import com.thoughtorigin.reflect.MetaDataItem;
import com.thoughtorigin.relay.MessageRelay;

import com.thoughtorigin.relay.ResponseEvent;

import flash.display.DisplayObject;

import flash.events.Event;

import flash.net.registerClassAlias;

import org.flexunit.asserts.assertNotNull;
import org.flexunit.asserts.assertTrue;
import org.flexunit.asserts.fail;
import org.flexunit.async.Async;
import org.mockito.integrations.any;
import org.mockito.integrations.atLeast;
import org.mockito.integrations.between;
import org.mockito.integrations.callOriginal;
import org.mockito.integrations.given;
import org.mockito.integrations.mock;
import org.mockito.integrations.verify;

[RunWith("org.mockito.integrations.flexunit4.MockitoClassRunner")]
[Mock(type="com.thoughtorigin.relay.MessageRelay")]
[Mock(type="com.thoughtorigin.meta.mock.SampleDisplayObject")]
[Mock(type="flash.events.Event")]
public class HandlerMetaDataTest {
    private var _handlerMetaData: HandlerMetaData;

    [Before]
    public function setup(): void {
        _handlerMetaData = new HandlerMetaData();
    }

    [After]
    public function tearDown(): void {
        _handlerMetaData = null;
    }

    [Test]
    public function shouldAddEventListenerToServiceLocator(): void {
        var callbackCalled: Boolean = false;
        var callback: Function = function(): void {
            verify(atLeast(1)).that(relay.addEventListener("sampleEvent", sample.sampleHandler));
            callbackCalled = true;
        };

        var sample: SampleComponent = new SampleComponent();
        var relay: MessageRelay = mock(MessageRelay);
        assertNotNull(relay);
        _handlerMetaData.messageRelay = relay;
        var metaData: MetaDataItem = new FunctionMetaDataItem("Handler", [new MetaArg("name", "sampleEvent")], "sampleHandler");
        _handlerMetaData.decorate(sample, metaData, callback);

        if(!callbackCalled) {
            fail();
        }

    }

    [Test]
    public function shouldDispose(): void {
        var sample: SampleDisplayObject = mock(SampleDisplayObject);
        var relay: MessageRelay = mock(MessageRelay);
        var event: Event = mock(Event, "", ["", false, false]);
        given(event.target).willReturn(sample);
        given(sample.removeEventListener(Event.REMOVED_FROM_STAGE, _handlerMetaData.dispose));
        given(relay.removeEventListener(any(), any()));
        _handlerMetaData.messageRelay = relay;
        var metaData: MetaDataItem = new FunctionMetaDataItem("Handler", [new MetaArg("name", "sampleEvent")], "sampleHandler");
        _handlerMetaData.decorate(sample, metaData, null);
        _handlerMetaData.dispose(event);

        verify(between(1,1)).that(event.target);
        verify(between(2,2)).that(sample.removeEventListener(Event.REMOVED_FROM_STAGE, _handlerMetaData.dispose));
        verify(between(2,2)).that(relay.removeEventListener(any(), any()));
    }

    [Test(async)]
    public function shouldAddEventListenerToObjectIfItsADisplayObject(): void {
        var sample: SampleDisplayObject = mock(SampleDisplayObject);
        var relay: MessageRelay = mock(MessageRelay);
        given(relay.addEventListener("sampleEvent", sample.sampleHandler));
        _handlerMetaData.messageRelay = relay;

        var callback: Function = Async.asyncHandler(this, function(): void {
            verify(atLeast(1)).that(relay.addEventListener("sampleEvent", sample.sampleHandler));
            verify(between(1,1)).that(sample.addEventListener(Event.REMOVED_FROM_STAGE, _handlerMetaData.dispose));
        }, 100);

        given(sample.addEventListener(Event.REMOVED_FROM_STAGE, _handlerMetaData.dispose)).will(callOriginal());

        var metaData: MetaDataItem = new FunctionMetaDataItem("Handler", [new MetaArg("name", "sampleEvent")], "sampleHandler");
        _handlerMetaData.decorate(sample, metaData, callback);
    }

    [Test]
    public function shouldOnlyAddOneListenerToTheMessageRelay(): void {
        var callbackCalled: Boolean = false;
        var callback: Function = function(): void {
            verify(between(1,1)).that(relay.addEventListener("sampleEvent", sample.sampleHandler));
            callbackCalled = true;
        };

        var sample: SampleComponent = new SampleComponent();
        var relay: MessageRelay = mock(MessageRelay);
        assertNotNull(relay);
        _handlerMetaData.messageRelay = relay;
        var metaData: MetaDataItem = new FunctionMetaDataItem("Handler", [new MetaArg("name", "sampleEvent")], "sampleHandler");
        _handlerMetaData.decorate(sample, metaData, null);
        _handlerMetaData.decorate(sample, metaData, callback);

        if(!callbackCalled) {
            fail();
        }
    }
}
}

import flash.display.DisplayObject;
import flash.events.Event;

class SampleComponent {
    public function sampleHandler(e: Event): void {

    }
}

